import { JSX } from 'react';
import { EDITOR_ELEMENT_TYPE, Plugin, commandType } from '@/plugins/types';
import { RenderElementProps, RenderLeafProps } from 'slate-react';
import { renderElement, onKeyDown, decorate, renderLeaf } from './render';
import { NodeEntry, Range } from 'slate';

type RenderPlugin = {
  renderElement?: (props: RenderElementProps) => JSX.Element;
  renderLeaf?: (props: RenderLeafProps) => JSX.Element;
  onKeyDown?: (event: KeyboardEvent) => void;
  decorate?: (entry: NodeEntry) => Range[];
};

/***
 * @Plugin 整合插件
 */
class Integration {
  private plugins: Plugin[];
  private command: Record<string, commandType>;

  constructor(...plugins: Plugin[]) {
    this.plugins = plugins;
    this.command = {};
  }
  public getCommand(): Record<string, commandType> {
    return this.command;
  }
  public addPlugin(...plugins: Plugin[]): void {
    this.plugins.push(...plugins);
  }

  public start(): RenderPlugin {
    const elementPlugins: Plugin[] = [];
    const leafPlugins: Plugin[] = [];
    // 先按照优先级进行排序 (会修改原始数组的内容)
    this.plugins.sort((a, b) => (b.priority || 0) - (a.priority || 0));
    this.plugins.forEach((plugin) => {
      if (plugin.type === EDITOR_ELEMENT_TYPE.BLOCK) {
        elementPlugins.push(plugin);
        if (plugin.matchLeaf && plugin.renderLeaf) {
          leafPlugins.push(plugin);
        }
      } else if (plugin.type === EDITOR_ELEMENT_TYPE.INLINE) {
        leafPlugins.push(plugin);
      }
      if (plugin.command) {
        this.command[plugin.key] = plugin.command;
      }
    });
    return {
      renderElement: (props) => {
        return renderElement(props, elementPlugins);
      },
      renderLeaf: (props) => {
        return renderLeaf(props, leafPlugins);
      },
      onKeyDown: (event) => {
        return onKeyDown(event, this.plugins);
      },
      decorate: (entry) => {
        return decorate(entry, this.plugins);
      },
    };
  }
}

export default Integration;
